#include "postgres.h"
#include "sql_translator.h"

//#include "a_spi.h"

/*for exec_simple_cmd*/
//#include "postgres.h"

#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/time.h>
#include <sys/resource.h>
#endif
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif

#ifndef HAVE_GETRUSAGE
#include "rusagestub.h"
#endif

#include "access/printtup.h"
#include "access/xact.h"
#include "catalog/pg_type.h"
#include "commands/async.h"
#include "commands/prepare.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
#include "libpq/pqsignal.h"
#include "miscadmin.h"
#include "nodes/print.h"
#include "optimizer/planner.h"
#include "pgstat.h"
#include "pg_trace.h"
#include "parser/analyze.h"
#include "parser/parser.h"
#include "postmaster/autovacuum.h"
#include "postmaster/postmaster.h"
#include "replication/walsender.h"
#include "rewrite/rewriteHandler.h"
#include "storage/bufmgr.h"
#include "storage/ipc.h"
#include "storage/proc.h"
#include "storage/procsignal.h"
#include "storage/sinval.h"
#include "tcop/fastpath.h"
#include "tcop/pquery.h"
#include "tcop/tcopprot.h"
#include "tcop/utility.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/ps_status.h"
#include "utils/snapmgr.h"
#include "mb/pg_wchar.h"


#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

int dq_execq(text *sql);

void test_exec(char * query_string){
    
    elog(INFO,"%s","call test_exec");
    
    CommandDest dest = DestRemote;
    //elog(INFO,"%s",whereToSendOutput);
    //CommandDest dest =DestSPI;
    MemoryContext oldcontext; /*for further processing*/
    List       *parsetree_list;
    ListCell   *parsetree_item;
    /**/
    
    
    
    oldcontext = MemoryContextSwitchTo(MessageContext);
    parsetree_list=pg_parse_query(query_string);
    
    foreach(parsetree_item,parsetree_list){
        Node * parsetree=(Node *)lfirst(parsetree_item);
        const char * commandTag;
        List  *querytree_list;
        List *plantree_list;
        Portal portal;
        int16 format;
        DestReceiver *receiver;
        char		completionTag[COMPLETION_TAG_BUFSIZE];
        
        commandTag = CreateCommandTag(parsetree);
        
		set_ps_display(commandTag, false);
        
		BeginCommand(commandTag, dest);
        
        
        
        querytree_list=pg_analyze_and_rewrite(parsetree,query_string,NULL,0);
        
        plantree_list=pg_plan_queries(querytree_list,0,NULL);
        
        /*
        ListCell * plantree_item;
        foreach(plantree_item,plantree_list){
            Node * plannode=(Node *) lfirst (plantree_item);
            Plan * plan_item=(Plan *) plannode;
            elog_node_display(LOG,"plan",plan_item,true);
    

        }
        //ådebug
         */
        
        /*create unamed portal to run the query or queries in
         if there already is one, siliently drop it.
         */
        
        if(IsA(parsetree,FetchStmt)){
            elog(INFO,"%s","is fetch stmt,then modified the format");
        }
        
        
        
        portal=CreatePortal("",true,true);
        
        portal->visible=false;
        
        PortalDefineQuery(portal,NULL,query_string,commandTag,plantree_list,NULL);
        elog(INFO,"%s","portal define query");
        PortalStart(portal, NULL, InvalidSnapshot);
        // format
        format=0;
        PortalSetResultFormat(portal, 1, &format); /*output format*/
        receiver = CreateDestReceiver(dest);
		if (dest == DestRemote){
            elog(INFO,"%s","destremote");
			SetRemoteDestReceiverParams(receiver, portal);
        }
        
    
        MemoryContextSwitchTo(oldcontext);
        
        
        /**/
        switch(portal->strategy){
                case PORTAL_ONE_SELECT:
                    elog(INFO,"%s","select");
                break;
            default:
                elog(INFO,"%s","others");
        }
        
        
        (void) PortalRun(portal,
						 FETCH_ALL,
						 true,
						 receiver,
						 receiver,
						 completionTag);
        
        
        /*here */
        
        
        //elog(INFO,"completeiontag:%s",completionTag);
        
        (*receiver->rDestroy) (receiver);
        
        PortalDrop(portal, false);
        
        
        /*
        if(IsA(parsetree,TransactionStmt)){
            finish_xact_command();
        }
        else if (lnext(parsetree_item)==NULL){
            
            finish_xact_command();
        }
        else {
            CommandCounterIncrement();
        }
        */
        
        EndCommand(completionTag,dest);
        
    }
    
    //finish_xact_command();
    
}


int dq_execq(text *sql){
    char * command;
    
    //
    //command=text_to_cstring(sql);
    //command="select * from computer,sale where computer.id=sale.id group by id;";
    command="select * from anno_table, data_anno where anno_table.id=data_anno.id ; ";
    
    List * raw_parsetree_list;
    raw_parsetree_list=raw_parser(command);
    ArtCmd * art_cmd=malloc(sizeof(ArtCmd));
    /*
    char* gen_anno_stmt=add_gen_anno_table();
    
    ListCell * list_item;
    foreach(list_item,raw_parsetree_list){
        Node * parsetree=(Node *) lfirst(list_item);
        if(IsA(parsetree,SelectStmt)){
            
            SelectStmt *stmt=(SelectStmt *) parsetree;
            
            
            }
        
        else{
            // do Nothing as Normal ones.
        }

    }
    */
    test_exec(command);
    
    return 1;
}
